/**
 * 自定义公共函数包
 * 这里可以写你自己的公共函数
 */
let pubFun = {};
/**
 * 公共函数写法示例
 * 调用示例：
 * pubFun.test();
 * 或
 * vk.myfn.test();
 */
pubFun.test = function (path) {
  // 可通过 uniCloud.vk 来获取vk实例
  let vk = uniCloud.vk;
  let timeStr = vk.pubfn.timeFormat(new Date(), "yyyy-MM-dd hh:mm:ss");
  // 逻辑
  // ...
  // 逻辑
  return {
    timeStr,
    msg: "这是公共函数test的返回",
  };
};

// ==================== 积分系统相关函数 ====================

/**
 * 计算购买卡密所需积分（基于产品）- 包量计费模式
 * @param {Object} product 产品信息
 * @param {Number} validDays 有效天数
 * @param {Number} count 购买数量
 * @param {Number} maxUseCount 允许使用的机器数量
 * @returns {Number} 所需积分
 */
pubFun.calculateProductPoints = function (
  product,
  validDays,
  count = 1,
  maxUseCount = 1
) {
  if (!product || !product.base_price) {
    return 0;
  }

  // 基础价格（每月每机器）
  const basePrice = product.base_price;

  // ==================== 简化计费模式（按机器数量直接计费）====================
  // 月价 = 单价 × 机器数
  const machinePrice = basePrice * maxUseCount;

  // ==================== 7天体验版特殊处理（固定价格）====================
  if (validDays === 7) {
    // 7天体验版：固定价格10积分
    const totalPoints = 10 * count;
    return totalPoints;
  }

  // 计算月数（年卡特殊处理为12个月）
  let months;
  if (validDays === 365) {
    months = 12;
  } else {
    months = Math.ceil(validDays / 30);
  }

  // 查找时长折扣
  let timeDiscount = 1;
  if (product.valid_days_options && Array.isArray(product.valid_days_options)) {
    const option = product.valid_days_options.find(
      (opt) => opt.days === validDays
    );
    if (option && option.discount) {
      timeDiscount = option.discount;
    }
  }

  // 总积分 = 月价 × 月数 × 时长折扣 × 购买数量
  const totalPoints = Math.ceil(machinePrice * months * timeDiscount * count);

  return totalPoints;
};

/**
 * 获取产品信息
 * @param {Object} vk vk实例
 * @param {String} productId 产品ID
 * @returns {Object} 产品信息
 */
pubFun.getProduct = async function (vk, productId) {
  const dbName = "vk-products";
  const res = await vk.baseDao.selects({
    dbName,
    whereJson: { product_id: productId, status: 1 },
  });

  // 处理返回数据格式
  let records = [];
  if (Array.isArray(res)) {
    records = res;
  } else if (res && res.rows) {
    records = res.rows;
  } else if (res && res.data) {
    records = res.data;
  }

  return records && records.length > 0 ? records[0] : null;
};

/**
 * 查询用户积分余额（如果不存在则自动创建）
 */
pubFun.getPointsBalance = async function (vk, userId) {
  const dbName = "vk-user-points";
  const res = await vk.baseDao.selects({
    dbName,
    whereJson: { user_id: userId },
  });

  // 处理返回数据格式
  let records = [];
  if (Array.isArray(res)) {
    records = res;
  } else if (res && res.rows) {
    records = res.rows;
  } else if (res && res.data) {
    records = res.data;
  }

  if (records && records.length > 0) {
    // 如果积分记录已存在，检查是否是管理员，如果是则确保积分为99999999
    const userRes = await vk.baseDao.selects({
      dbName: "uni-id-users",
      whereJson: { _id: userId },
    });

    let userRecords = [];
    if (Array.isArray(userRes)) {
      userRecords = userRes;
    } else if (userRes && userRes.rows) {
      userRecords = userRes.rows;
    } else if (userRes && userRes.data) {
      userRecords = userRes.data;
    }

    // 判断是否是管理员
    const isAdmin =
      userRecords &&
      userRecords.length > 0 &&
      userRecords[0].role &&
      Array.isArray(userRecords[0].role) &&
      userRecords[0].role.includes("admin");

    // 如果是管理员且积分不足99999999，自动补充
    if (isAdmin && records[0].available_points < 99999999) {
      const adminPoints = 99999999;
      try {
        await vk.baseDao.update({
          dbName,
          whereJson: { user_id: userId },
          dataJson: {
            total_points: adminPoints,
            available_points: adminPoints,
            _update_time: Date.now(),
          },
        });
        // 返回更新后的数据
        return {
          ...records[0],
          total_points: adminPoints,
          available_points: adminPoints,
        };
      } catch (err) {
        console.error("更新管理员积分失败：", err);
      }
    }

    return records[0];
  }

  // 如果用户没有积分记录，自动创建
  // 查询用户信息，判断是否是管理员
  const userRes = await vk.baseDao.selects({
    dbName: "uni-id-users",
    whereJson: { _id: userId },
  });

  let userRecords = [];
  if (Array.isArray(userRes)) {
    userRecords = userRes;
  } else if (userRes && userRes.rows) {
    userRecords = userRes.rows;
  } else if (userRes && userRes.data) {
    userRecords = userRes.data;
  }

  // 判断是否是管理员
  const isAdmin =
    userRecords &&
    userRecords.length > 0 &&
    userRecords[0].role &&
    Array.isArray(userRecords[0].role) &&
    userRecords[0].role.includes("admin");

  // 管理员默认99999999积分，普通用户0积分
  const defaultPoints = isAdmin ? 99999999 : 0;

  const newAccount = {
    user_id: userId,
    total_points: defaultPoints,
    available_points: defaultPoints,
    frozen_points: 0,
    consumed_points: 0,
    _add_time: Date.now(),
  };

  try {
    await vk.baseDao.add({
      dbName,
      dataJson: newAccount,
    });
  } catch (err) {
    console.error("创建积分账户失败：", err);
  }

  return newAccount;
};

/**
 * 初始化用户积分账户
 */
pubFun.initUserPoints = async function (vk, userId) {
  const dbName = "vk-user-points";

  // 检查是否已存在
  const res = await vk.baseDao.selects({
    dbName,
    whereJson: { user_id: userId },
  });

  // 处理返回数据格式
  let existing = [];
  if (Array.isArray(res)) {
    existing = res;
  } else if (res && res.rows) {
    existing = res.rows;
  } else if (res && res.data) {
    existing = res.data;
  }

  if (existing && existing.length > 0) {
    return existing[0];
  }

  // 查询用户信息，判断是否是管理员
  const userRes = await vk.baseDao.selects({
    dbName: "uni-id-users",
    whereJson: { _id: userId },
  });

  let userRecords = [];
  if (Array.isArray(userRes)) {
    userRecords = userRes;
  } else if (userRes && userRes.rows) {
    userRecords = userRes.rows;
  } else if (userRes && userRes.data) {
    userRecords = userRes.data;
  }

  // 判断是否是管理员
  const isAdmin =
    userRecords &&
    userRecords.length > 0 &&
    userRecords[0].role &&
    Array.isArray(userRecords[0].role) &&
    userRecords[0].role.includes("admin");

  // 管理员默认99999999积分，普通用户0积分
  const defaultPoints = isAdmin ? 99999999 : 0;

  // 创建积分账户
  const addRes = await vk.baseDao.add({
    dbName,
    dataJson: {
      user_id: userId,
      total_points: defaultPoints,
      available_points: defaultPoints,
      frozen_points: 0,
      consumed_points: 0,
      _add_time: Date.now(),
      _update_time: Date.now(),
    },
  });

  return {
    _id: addRes.id,
    user_id: userId,
    total_points: defaultPoints,
    available_points: defaultPoints,
    frozen_points: 0,
    consumed_points: 0,
  };
};

/**
 * 增加用户积分
 */
pubFun.addPoints = async function (
  vk,
  userId,
  amount,
  source,
  remark,
  orderId = "",
  cardId = ""
) {
  const dbName = "vk-user-points";
  const logDbName = "vk-points-log";

  // 确保用户有积分账户
  await pubFun.initUserPoints(vk, userId);

  // 获取当前积分记录（包含_id）
  const selectResult = await vk.baseDao.selects({
    dbName,
    whereJson: { user_id: userId },
  });

  console.log("selects返回结果:", selectResult);
  console.log("selects返回类型:", typeof selectResult);
  console.log("是否有rows:", selectResult && selectResult.rows);

  // 处理不同的返回格式
  let records = [];
  if (Array.isArray(selectResult)) {
    records = selectResult;
  } else if (selectResult && selectResult.rows) {
    records = selectResult.rows;
  } else if (selectResult && selectResult.data) {
    records = selectResult.data;
  }

  console.log("解析后的records:", records);

  if (!records || records.length === 0) {
    return {
      success: false,
      message: "积分账户不存在",
    };
  }

  const currentRecord = records[0];
  console.log("当前积分记录:", currentRecord);

  // 计算新的积分
  const newTotalPoints = currentRecord.total_points + amount;
  const newAvailablePoints = currentRecord.available_points + amount;

  console.log("准备更新积分:", {
    _id: currentRecord._id,
    user_id: userId,
    new_total: newTotalPoints,
    new_available: newAvailablePoints,
  });

  // 使用 updateById 更新（最可靠的方式）
  const updateRes = await vk.baseDao.updateById({
    dbName,
    id: currentRecord._id,
    dataJson: {
      total_points: newTotalPoints,
      available_points: newAvailablePoints,
      _update_time: Date.now(),
    },
  });

  console.log("更新结果:", updateRes);

  // 获取更新后的余额
  const balance = await pubFun.getPointsBalance(vk, userId);
  console.log("更新后积分:", balance);

  // 记录流水
  await vk.baseDao.add({
    dbName: logDbName,
    dataJson: {
      user_id: userId,
      type: amount > 0 ? "income" : "expense",
      amount: amount,
      balance: balance.available_points,
      source: source,
      order_id: orderId,
      card_id: cardId,
      remark: remark,
      _add_time: Date.now(),
    },
  });

  return {
    success: true,
    balance: balance.available_points,
  };
};

/**
 * 扣除用户积分
 */
pubFun.consumePoints = async function (
  vk,
  userId,
  amount,
  source,
  remark,
  orderId = "",
  cardId = ""
) {
  const dbName = "vk-user-points";
  const logDbName = "vk-points-log";

  // 获取当前积分记录（包含_id）
  const selectResult = await vk.baseDao.selects({
    dbName,
    whereJson: { user_id: userId },
  });

  // 处理不同的返回格式
  let records = [];
  if (Array.isArray(selectResult)) {
    records = selectResult;
  } else if (selectResult && selectResult.rows) {
    records = selectResult.rows;
  } else if (selectResult && selectResult.data) {
    records = selectResult.data;
  }

  if (!records || records.length === 0) {
    return {
      success: false,
      message: "积分账户不存在",
    };
  }

  const currentRecord = records[0];

  // 检查积分是否足够
  if (currentRecord.available_points < amount) {
    return {
      success: false,
      message: `积分不足，当前可用积分：${currentRecord.available_points}，需要：${amount}`,
    };
  }

  // 扣除积分（使用 updateById）
  await vk.baseDao.updateById({
    dbName,
    id: currentRecord._id,
    dataJson: {
      available_points: currentRecord.available_points - amount,
      consumed_points: currentRecord.consumed_points + amount,
      _update_time: Date.now(),
    },
  });

  // 获取更新后的余额
  const newBalance = await pubFun.getPointsBalance(vk, userId);

  // 记录流水
  await vk.baseDao.add({
    dbName: logDbName,
    dataJson: {
      user_id: userId,
      type: "consume",
      amount: -amount,
      balance: newBalance.available_points,
      source: source,
      order_id: orderId,
      card_id: cardId,
      remark: remark,
      _add_time: Date.now(),
    },
  });

  return {
    success: true,
    balance: newBalance.available_points,
  };
};

// ==================== 新卡密系统工具函数 ====================

const crypto = require("crypto");

/**
 * 生成随机字符串
 * @param {Number} length 长度
 * @returns {String}
 */
pubFun.generateRandomString = function (length) {
  return crypto
    .randomBytes(Math.ceil(length / 2))
    .toString("hex")
    .slice(0, length);
};

/**
 * 生成唯一密钥
 * @param {Number} num 数量
 * @param {Number} length 长度
 * @returns {Array<String>}
 */
pubFun.generateUniqueKeys = function (num, length) {
  const keys = new Set(); // 使用 Set 来确保唯一性
  while (keys.size < num) {
    keys.add(pubFun.generateRandomString(length));
  }
  return Array.from(keys);
};

/**
 * 通用参数获取函数 - 兼容函数参数和HTTP请求参数
 * @param {Object} funcParams 函数参数
 * @param {Object} httpInfo HTTP请求信息
 * @returns {Object} 合并后的参数
 */
pubFun.getParams = function (funcParams, httpInfo) {
  // 解析 HTTP 请求体
  let httpParams = {};
  if (httpInfo && httpInfo.body) {
    try {
      // body 可能是对象或字符串
      httpParams =
        typeof httpInfo.body === "string"
          ? JSON.parse(httpInfo.body)
          : httpInfo.body;
    } catch (error) {
      console.error("解析HTTP请求体失败:", error);
      httpParams = {};
    }
  }

  // 处理函数入参：仅保留已定义的键，避免 undefined 覆盖 http 参数
  const safeFuncParams =
    funcParams && typeof funcParams === "object"
      ? Object.fromEntries(
          Object.entries(funcParams).filter(([_, v]) => v !== undefined)
        )
      : {};

  // 如果函数参数没有任何有效值，则直接返回 http 参数
  if (Object.keys(safeFuncParams).length === 0) {
    return httpParams || {};
  }

  // 合并，函数参数优先（因为显式传入）
  return Object.assign({}, httpParams || {}, safeFuncParams);
};

/**
 * 极简卡密校验函数 - 基于字段值直接校验
 * @param {Object} record 卡密记录
 * @param {String} machineCode 机器码（可选）
 * @param {String} user_id 当前用户ID（必需）
 * @returns {Object} 校验结果 { valid, message, updateData }
 */
pubFun.validateCardKey = function (record, machineCode = null, user_id = null) {
  const updateData = {};

  // 用户ID校验：确保只有购买者能使用
  if (user_id && record.buy_user_id) {
    if (user_id !== record.buy_user_id) {
      return { valid: false, message: "此卡密不属于您，无法使用" };
    }
  }

  // 时间校验：limit_days !== -1 才校验
  if (record.limit_days !== -1) {
    const now = Date.now();

    // 首次使用设置时间
    if (record.activate_time === 0) {
      updateData.activate_time = now;
      updateData.expire_time = now + record.limit_days * 24 * 60 * 60 * 1000;
    } else if (now > record.expire_time) {
      return { valid: false, message: "卡密已过期" };
    }
  }

  // 次数校验：total_times !== -1 才校验
  if (record.total_times !== -1) {
    if (record.remaining_times <= 0) {
      return { valid: false, message: "使用次数已用完" };
    }
    updateData.used_times = record.used_times + 1;
    updateData.remaining_times = record.remaining_times - 1;
  }

  // 机器码校验：max_machine_count !== -1 才校验
  if (record.max_machine_count !== -1) {
    // 限制机器数量时，必须提供机器码
    if (!machineCode) {
      return { valid: false, message: "此卡密需要提供机器码" };
    }

    const machines = record.authorized_machines || [];

    if (!machines.includes(machineCode)) {
      if (machines.length >= record.max_machine_count) {
        return { valid: false, message: "已达到最大授权机器数量" };
      }
      updateData.authorized_machines = [...machines, machineCode];
    }
  }

  return {
    valid: true,
    message: "校验成功",
    updateData: Object.keys(updateData).length > 0 ? updateData : null,
  };
};

/**
 * 导出卡密到CSV（返回CSV内容字符串）
 * @param {Array<String>} ids 卡密ID列表
 * @param {Object} db 数据库实例
 * @returns {Object} { csvContent, count, message }
 */
pubFun.exportCardsToCSV = async function (ids, db) {
  if (!Array.isArray(ids) || ids.length === 0) {
    return {
      csvContent: null,
      count: 0,
      message: "无有效的卡密ID",
    };
  }

  const $ = db.command;
  const collection = db.collection("vk-card-key");
  const res = await collection
    .where({
      _id: $.in(ids),
    })
    .field({
      _id: true,
      card_code: true,
      limit_days: true,
      max_machine_count: true,
    })
    .get();

  const rows = res.data || [];

  // 列定义：key 为数据库字段，label 为导出标题
  const columns = [
    { key: "_id", label: "卡号" },
    { key: "card_code", label: "密钥" },
    { key: "limit_days", label: "有效期（天）" },
    { key: "max_machine_count", label: "最大机器数" },
  ];

  const headers = columns.map((c) => c.label);

  const esc = (v) => {
    if (v === undefined || v === null) return "";
    const s = String(v).replace(/"/g, '""');
    return `"${s}"`;
  };

  const csvRows = rows.map((r) => columns.map((c) => esc(r[c.key])).join(","));
  const csv = [headers.join(","), ...csvRows].join("\r\n");

  return {
    csvContent: csv,
    count: rows.length,
    message: "CSV 导出完成",
  };
};

module.exports = pubFun;
